package com.noahsloan.nutils.net;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

/**
 * Utility Class for making a UDP packet out of an InputStream.
 * 
 * Intended primarily for command line use.
 * 
 * @author Noah Sloan
 * 
 */
public class MakeUdp {

    /**
     * @param args
     *            [0] - address:port [1] - (optional) input file name, if not
     *            specified, reads from std in.
     */
    public static void main(String[] args) {
        String[] split;
        try {
            split = args[0].split(":", 2);
        } catch (IndexOutOfBoundsException e) {
            usage();
            return;
        }
        DatagramSocket sock = null;
        try {
            InputStream in = args.length > 1 ? new FileInputStream(args[1])
                    : System.in;
            sock = new DatagramSocket();
            sock.send(makePacket(split[0], Integer.parseInt(split[1]), in));
        } catch (NumberFormatException e) {
            System.err.printf("Invalid port number '%s'.", split[1]);
            usage();
        } catch (FileNotFoundException e) {
            System.err.printf("File not found '%s'", split[0]);
            usage();
        } catch (Exception e) {
            System.err.println(e.getLocalizedMessage());
            usage();
        } finally {
            try {
                sock.close();
            } catch (Exception e) {
                // ignore
            }
        }
        System.out.println("Message Sent");
    }

    private static void usage() {
        System.out.println("Parameters: <address>:<port> [filename]\n\t"
                + "If no filename is supplied, reads from standard input.");
    }

    /**
     * Same as {@link #makePacket(InetAddress, int, InputStream)} but resolves
     * host to an InetAddres first.
     * 
     * @param host
     * @param port
     * @param in
     * @return
     * @throws IOException
     * @see #makePacket(InetAddress, int, InputStream)
     */
    public static DatagramPacket makePacket(String host, int port,
            InputStream in) throws IOException {
        return makePacket(InetAddress.getByName(host), port, in);
    }

    /**
     * Creates a DatagramPacket addressed to the given address and port, reading
     * all the data from the given stream.
     * 
     * @param host
     * @param port
     * @param in
     * @return a new DatagramPacket
     * @throws IOException
     */
    public static DatagramPacket makePacket(InetAddress host, int port,
            InputStream in) throws IOException {
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        byte[] buff = new byte[1024];
        int i;
        while ((i = in.read(buff, 0, buff.length)) != -1) {
            bout.write(buff, 0, i);
        }
        buff = bout.toByteArray();
        return new DatagramPacket(buff, buff.length, host, port);
    }

}
